package mrusanov.nation

import mrusanov.tournament.{ KnockOutRoundTournamentReward, KnockOutTournamentRound, RoundRobinTournamentRound, Tournament }
import mrusanov.team.Club
import mrusanov.season.{ NationSeason, WorldSeason }
import java.util.{ Calendar, Date }
import mrusanov.util.DateUtil
import mrusanov.tournament.MatchInfo

object World {

	private def startDate: Date = {
		val calendar = Calendar.getInstance()
		calendar.clear()
		calendar.set(Calendar.YEAR, 1000)
		calendar.set(Calendar.MONTH, Calendar.JANUARY)
		calendar.set(Calendar.DAY_OF_MONTH, 1)
		calendar.getTime
	}

	def generateWorld: World = {
		val nations = NationsLoader.nations
		val clubGenerator = new ClubGenerator(startDate)
		nations foreach (clubGenerator.generateClubs)
		val world = new World(startDate, nations.toList)

		world.nextSeason()
		world
	}
}

class World(startDate: Date, val nations: List[Nation]) {
	val nationRatings = nations.map(new NationRatingEntry(_))
	var seasons = Vector[WorldSeason]()
	var userClub: Club = _

	private val _today = Calendar.getInstance()
	_today.setTime(startDate)

	def today = _today.getTime

	def nextDay() {
		val lastDayOfSeason = isLastDayOfSeason
		_today.add(Calendar.DAY_OF_YEAR, 1)
		if (lastDayOfSeason) {
			nextSeason()
		}
	}

	def currentYear = currentSeason.year

	def currentSeason = seasons.last

	def season(year: Int) = seasons(currentYear - year)

	private var _clubRatingMap: Map[Club, Int] = _
	def clubRatingMap = _clubRatingMap

	private var _clubRatingList: List[Club] = _

	def clubRatingList = _clubRatingList
	private val allClubs = nations.flatMap(_.clubs)

	def refreshClubRating() {
		_clubRatingList = allClubs.sortBy(_.firstTeam.rating)
		_clubRatingMap = _clubRatingList.zipWithIndex.toMap.map(kv => (kv._1, kv._2 + 1))
	}

	private def nextSeason() {
		val year = _today.get(Calendar.YEAR)
		val nationSeasons = nations map (n => new NationSeason(n.leagueInfoSystem, n, year))
		val season = new WorldSeason(this, year, Vector() ++ nationSeasons)
		seasons :+= season
	}

	// returns dates of events
	def userTeamEventToday: Option[UserEvent] = {
		if (!firstTeamMatchesToday.isEmpty && !firstTeamMatchesToday(0).isOver) {
			Some(BattleEvent)
		} else if (isLastDayOfSeason) {
			Some(EndOfSeasonEvent)
		} else if (isLastDayOfWeek) {
			Some(EndOfWeekEvent)
		} else {
			None
		}
	}

	private def firstTeamMatchesToday = currentSeason.teamsGames(userClub.firstTeam).filter(
		m => DateUtil.dateOnly(m.time).getTime == DateUtil.dateOnly(today).getTime)

	def userTeamBattleToday: Option[MatchInfo] = {
		if (firstTeamMatchesToday.isEmpty) {
			None
		} else {
			Some(firstTeamMatchesToday(0))
		}
	}

	private def isLastDayOfSeason: Boolean = {
		val calendar = Calendar.getInstance()
		calendar.setTime(today)
		val yearBefore = calendar.get(Calendar.YEAR)
		calendar.add(Calendar.DAY_OF_YEAR, 1)
		val yearAfter = calendar.get(Calendar.YEAR)
		yearBefore != yearAfter
	}

	private def isLastDayOfWeek: Boolean = {
		val dayOfWeek = _today.get(Calendar.DAY_OF_WEEK)
		dayOfWeek == Calendar.SUNDAY
	}

}

